import pygame
import pymunk
import random
import math

pygame.init()
width, height = 800, 600
screen = pygame.display.set_mode((width, height))
clock = pygame.time.Clock()

space = pymunk.Space()
space.gravity = (0, 0)

def add_ball(space, pos, radius=10, mass=1):
    moment = pymunk.moment_for_circle(mass, 0, radius)
    body = pymunk.Body(mass, moment)
    body.position = pos
    angle = random.uniform(0, 2 * math.pi)
    speed = 150
    body.velocity = (math.cos(angle) * speed, math.sin(angle) * speed)
    shape = pymunk.Circle(body, radius)
    shape.elasticity = 1.0
    shape.friction = 0.0
    space.add(body, shape)
    return shape

def add_triangle_ball(space, pos, size=20, mass=1):
    # 三角形顶点，中心在body位置
    vertices = [(-size/2, -size/2), (size/2, -size/2), (0, size/2)]
    moment = pymunk.moment_for_poly(mass, vertices)
    body = pymunk.Body(mass, moment)
    body.position = pos
    angle = random.uniform(0, 2 * math.pi)
    speed = 150
    body.velocity = (math.cos(angle) * speed, math.sin(angle) * speed)
    shape = pymunk.Poly(body, vertices)
    shape.elasticity = 1.0
    shape.friction = 0.0
    space.add(body, shape)
    return shape

def add_wall(space, start, end, thickness=5):
    body = pymunk.Body(body_type=pymunk.Body.STATIC)
    shape = pymunk.Segment(body, start, end, thickness)
    shape.elasticity = 1.0
    shape.friction = 0.0
    space.add(body, shape)
    return shape

# 计算规则八边形顶点
cx, cy = width / 2, height / 2
radius = min(width, height) * 0.4
num_sides = 8
angle_step = 2 * math.pi / num_sides
vertices = []
for i in range(num_sides):
    angle = angle_step * i - math.pi / 8
    x = cx + radius * math.cos(angle)
    y = cy + radius * math.sin(angle)
    vertices.append((x, y))

# 添加八边形边界墙
walls = []
for i in range(num_sides):
    start = vertices[i]
    end = vertices[(i + 1) % num_sides]
    wall = add_wall(space, start, end, thickness=5)
    walls.append(wall)

# 射线法判断点是否在多边形内
def point_in_polygon(x, y, poly):
    num = len(poly)
    j = num - 1
    inside = False
    for i in range(num):
        xi, yi = poly[i]
        xj, yj = poly[j]
        if ((yi > y) != (yj > y)) and (x < (xj - xi) * (y - yi) / (yj - yi + 1e-10) + xi):
            inside = not inside
        j = i
    return inside

balls = []
triangle_balls = []

# 生成10个圆形小球
while len(balls) < 10:
    x = random.uniform(cx - radius, cx + radius)
    y = random.uniform(cy - radius, cy + radius)
    if point_in_polygon(x, y, vertices):
        balls.append(add_ball(space, (x, y)))

# 生成5个三角形小球
while len(triangle_balls) < 5:
    x = random.uniform(cx - radius, cx + radius)
    y = random.uniform(cy - radius, cy + radius)
    if point_in_polygon(x, y, vertices):
        triangle_balls.append(add_triangle_ball(space, (x, y)))

font = pygame.font.SysFont(None, 24)

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    screen.fill((30, 30, 30))

    # 画八边形边界线
    for i in range(num_sides):
        start = vertices[i]
        end = vertices[(i + 1) % num_sides]
        pygame.draw.line(screen, (255, 0, 0), start, end, 3)

    # 画圆形小球
    for ball in balls:
        pos = int(ball.body.position.x), int(ball.body.position.y)
        pygame.draw.circle(screen, (100, 255, 100), pos, int(ball.radius))

    # 画三角形小球
    for tri in triangle_balls:
        points = [tri.body.local_to_world(v) for v in tri.get_vertices()]
        points = [(int(p.x), int(p.y)) for p in points]
        pygame.draw.polygon(screen, (255, 200, 50), points)

    # 显示FPS
    fps = clock.get_fps()
    fps_text = font.render(f"FPS: {fps:.2f}", True, (255, 255, 255))
    screen.blit(fps_text, (10, 10))

    pygame.display.flip()
    space.step(1 / 120.0)
    clock.tick(60)

pygame.quit()
